package net.thxjj.adminServer.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ctg.ag.sdk.biz.AepDeviceEventClient;
import com.ctg.ag.sdk.biz.AepDeviceStatusClient;
import com.ctg.ag.sdk.biz.aep_device_event.QueryDeviceEventListRequest;
import com.ctg.ag.sdk.biz.aep_device_event.QueryDeviceEventListResponse;
import com.ctg.ag.sdk.biz.aep_device_status.GetDeviceStatusHisInPageRequest;
import com.ctg.ag.sdk.biz.aep_device_status.GetDeviceStatusHisInPageResponse;
import net.thxjj.adminServer.dao.*;
import net.thxjj.adminServer.entity.*;
import net.thxjj.adminServer.entity.aep.DevLog;
import net.thxjj.adminServer.entity.aep.HeartData;
import net.thxjj.adminServer.entity.aep.LoginData;
import net.thxjj.adminServer.entity.aep.SmokeData;
import net.thxjj.adminServer.mongodao.*;
import net.thxjj.adminServer.util.ParameterMap;
import net.thxjj.sitermodel.Device;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import net.thxjj.adminServer.service.IDevLogService;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Service
public class DevLogService implements IDevLogService {
	private Logger log = Logger.getLogger(this.getClass());
	@Autowired
	private DeviceDao deviceDao;
	@Autowired
	private MongoLoginDao mongoLoginDao;
	@Autowired
	private MongoSmokeDao mongoSmokeDao;
	@Autowired
	private MongoHeartDao mongoHeartDao;
	@Autowired
	private MongoLoginHandleDao mongoLoginHandleDao;
	@Autowired
	private MongoEventDao mongoEventDao;

	@Override
	public void addEvent(List<DevLog> list) {
		mongoEventDao.saveDevLogs(list);
	}

	@Override
	public void addData(List<HeartData> list, List<SmokeData> listsmoke, List<LoginData> listlogin) {


		try {
			if(list.size()>0)
				mongoHeartDao.saveHeartDatas(list);
			if(listsmoke.size()>0)
				mongoSmokeDao.saveSmokeDatas(listsmoke);
			if(listlogin.size()>0)
				mongoLoginDao.saveLoginDatas(listlogin);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("error:"+e.getMessage(), e);
		}

	}

	@Override
	public ParameterMap SmokeAlarmStatus(String device_id) {
		DevLog devLogSmoke = mongoEventDao.getNewstEvent(device_id,"\"smoke_state\":0");
		SmokeData devStatusSmoke = mongoSmokeDao.getNewestSmokeAlarm(device_id);
		DevLog devLogSmokeNor = mongoEventDao.getNewstEvent(device_id,"\"smoke_state\":1");
		SmokeData devStatusSmokeNor = mongoSmokeDao.getNewestSmokeNormal(device_id);

		long devLogSmoke_time = (devLogSmoke==null?0:devLogSmoke.getCreateTime());
		long devStatusSmoke_time = (devStatusSmoke==null?0:devStatusSmoke.getTimestamp());
		long devLogSmokeNor_time = (devLogSmokeNor==null?0:devLogSmokeNor.getCreateTime());
		long devStatusSmokeNor_time = (devStatusSmokeNor==null?0:devStatusSmokeNor.getTimestamp());

		long totoal_happen = Math.max(devLogSmoke_time,devStatusSmoke_time);
		long totoal_happen_huifu = Math.max(devLogSmokeNor_time,devStatusSmokeNor_time);

		if(totoal_happen<=totoal_happen_huifu){
			ParameterMap map = new ParameterMap();
			map.put("datasetId","smoke_state");
			map.put("value",0);
			map.put("timestamp",totoal_happen_huifu);
			return map;
		}else{
			ParameterMap map = new ParameterMap();
			map.put("datasetId","smoke_state");
			map.put("value",1);
			map.put("timestamp",totoal_happen);
			return map;
		}
	}

	@Override
	public ParameterMap SensorFault(String device_id) {
		DevLog sensorFault = mongoEventDao.getNewstEvent(device_id,"\"error\":1");
		DevLog sensorFaultNor = mongoEventDao.getNewstEvent(device_id,"\"error\":2");

		long sensorFault_time = (sensorFault==null?0:sensorFault.getCreateTime());
		long sensorFault_time_nor = (sensorFaultNor==null?0:sensorFaultNor.getCreateTime());

		if(sensorFault_time<=sensorFault_time_nor){
			ParameterMap map = new ParameterMap();
			map.put("datasetId","sensor_fault");
			map.put("value",0);
			map.put("timestamp",sensorFault_time_nor);
			return map;
		}else{
			ParameterMap map = new ParameterMap();
			map.put("datasetId","sensor_fault");
			map.put("value",1);
			map.put("timestamp",sensorFault_time);
			return map;
		}

	}

	@Override
	public ParameterMap LowVoltFault(String device_id) {
		DevLog lowVoltFault = mongoEventDao.getNewstEvent(device_id,"\"error\":3");
		DevLog lowVoltFaultNor = mongoEventDao.getNewstEvent(device_id,"\"error\":4");

		long lowVoltFault_time = (lowVoltFault==null?0:lowVoltFault.getCreateTime());
		long lowVoltFault_time_nor = (lowVoltFaultNor==null?0:lowVoltFaultNor.getCreateTime());

		if(lowVoltFault_time<=lowVoltFault_time_nor){
			ParameterMap map = new ParameterMap();
			map.put("datasetId","low_voltage");
			map.put("value",0);
			map.put("timestamp",lowVoltFault_time_nor);
			return map;
		}else{
			ParameterMap map = new ParameterMap();
			map.put("datasetId","low_voltage");
			map.put("value",1);
			map.put("timestamp",lowVoltFault_time);
			return map;
		}
	}

	@Override
	public ParameterMap DismantleStatus(String device_id) {
		DevLog dismantle = mongoEventDao.getNewstEvent(device_id,"\"tamper_alarm\":1");
		DevLog dismantleNor = mongoEventDao.getNewstEvent(device_id,"\"tamper_alarm\":0");

		long dismantle_time = (dismantle==null?0:dismantle.getCreateTime());
		long dismantle_time_nor = (dismantleNor==null?0:dismantleNor.getCreateTime());

		if(dismantle_time<=dismantle_time_nor){
			ParameterMap map = new ParameterMap();
			map.put("datasetId","dismantle");
			map.put("value",0);
			map.put("timestamp",dismantle_time_nor);
			return map;
		}else{
			ParameterMap map = new ParameterMap();
			map.put("datasetId","dismantle");
			map.put("value",1);
			map.put("timestamp",dismantle_time);
			return map;
		}
	}

	@Override
	public ParameterMap SmokeValue(String device_id) {
		SmokeData data_smoke_1 = mongoSmokeDao.getNewestSmoke(device_id);
		DevLog data_smoke_2 = mongoEventDao.getNewstEvent(device_id,"smoke_value");

		long data_smoke_1_time = (data_smoke_1==null?0:data_smoke_1.getTimestamp());
		long data_smoke_2_time = (data_smoke_2==null?0:data_smoke_2.getCreateTime());

		long value = 0;
		if(data_smoke_1_time>data_smoke_2_time){
			if(data_smoke_1!=null)
			value = data_smoke_1.getSmoke_value();
		}else{
			if(data_smoke_2!=null){
				try {
					String eventcontent = data_smoke_2.getEventContent();
					JSONObject jsonObject = JSON.parseObject(eventcontent);
					value = jsonObject.getIntValue("smoke_value");
				}catch (Exception e){
					e.printStackTrace();
				}
			}

		}

		ParameterMap map = new ParameterMap();
		map.put("datasetId","smoke_value");
		map.put("value",value);
		map.put("timestamp",Math.max(data_smoke_1_time,data_smoke_2_time));

		return map;
	}

	@Override
	public ParameterMap BatteryValue(String device_id) {
		HeartData heartData = mongoHeartDao.getNewestHeartBeat(device_id);
		DevLog devLog = mongoEventDao.getNewstEvent(device_id,"battery_value");
		SmokeData smokeData = mongoSmokeDao.getNewestSmoke(device_id);
		long heartData_time = (heartData==null?0:heartData.getTimestamp());
		long devLog_time = (devLog==null?0:devLog.getCreateTime());
		long smokeData_time = (smokeData==null?0:smokeData.getTimestamp());

		long battery_value = 0;
		long de =Math.max(Math.max(heartData_time,devLog_time),smokeData_time);
		if(de==heartData_time){
			if(heartData!=null)
			battery_value = heartData.getBattery_value();
		}else{
			if(de == devLog_time){
				try {
					if(devLog!=null){
						String eventContent = devLog.getEventContent();
						JSONObject jsonObject = JSON.parseObject(eventContent);
						battery_value = jsonObject.getIntValue("battery_value");
					}
				}catch (Exception e){
					e.printStackTrace();
				}

			}else{
				if(smokeData!=null)
					battery_value = smokeData.getBattery_value();
			}
		}
		ParameterMap map = new ParameterMap();
		map.put("datasetId","battery_value");
		map.put("value",battery_value);
		map.put("timestamp",de);

		return map;
	}

	@Override
	public ParameterMap BatteryVoltage(String device_id) {
		HeartData heartData = mongoHeartDao.getNewestHeartBeat(device_id);
		if(heartData!=null){
			ParameterMap map = new ParameterMap();
			map.put("datasetId","battery_voltage");
			map.put("value",heartData.getBattery_voltage());
			map.put("timestamp",heartData.getTimestamp());
			return map;
		}else{
			ParameterMap map = new ParameterMap();
			map.put("datasetId","battery_voltage");
			map.put("value",0);
			map.put("timestamp",0);
			return map;
		}
	}

	@Override
	public ParameterMap SoftWareVersion(String device_id) {
		LoginData loginData = mongoLoginDao.getNewestLoginInfo(device_id);
		HeartData heartData = mongoHeartDao.getNewestHeartBeat(device_id);
		long loginData_time = (loginData==null?0:loginData.getTimestamp());
		long heartData_time = (heartData==null?0:heartData.getTimestamp());
		long de = Math.max(loginData_time,heartData_time);
		String soft = "";
		if(de==loginData_time){
			if(loginData!=null)
			soft = loginData.getSoftware_version();
		}else{
			if(heartData!=null)
				soft = heartData.getSoftware_version();
		}
		ParameterMap map = new ParameterMap();
		map.put("datasetId","software_version");
		map.put("value",soft);
		map.put("timestamp",de);
		return map;
	}

	@Override
	public ParameterMap HardWareVersion(String device_id) {
		LoginData loginData = mongoLoginDao.getNewestLoginInfo(device_id);
		HeartData heartData = mongoHeartDao.getNewestHeartBeat(device_id);
		long loginData_time = (loginData==null?0:loginData.getTimestamp());
		long heartData_time = (heartData==null?0:heartData.getTimestamp());
		long de = Math.max(loginData_time,heartData_time);
		String hard = "";
		if(de==loginData_time){
			if(loginData!=null)
				hard = loginData.getHardware_version();
		}else{
			if(heartData!=null)
				hard = heartData.getHardware_version();
		}
		ParameterMap map = new ParameterMap();
		map.put("datasetId","hardware_version");
		map.put("value",hard);
		map.put("timestamp",de);
		return map;
	}

	@Override
	public ParameterMap HeartBeat(String device_id) {
		int heartbeart = mongoHeartDao.getHeartBeatTotalNum(device_id);

		if(heartbeart==0){
			ParameterMap map = new ParameterMap();
			map.put("datasetId","heartbeat");
			map.put("value",0);
			return map;
		}

		long set_heart_time;
		Device device = deviceDao.getDeviceInfo(device_id);
		if(device.getHeartTime()<=0){
			set_heart_time = 1200;
		}else {
			set_heart_time = device.getHeartTime();
		}
		long heartbeart_lilun = 0;
		long heartlv = 0;
		HeartData data = mongoHeartDao.getEarliestHeartBeat(device_id);
		if(data!=null){
			long timelong = data.getTimestamp();
			long cur_timelong = System.currentTimeMillis();
			if(cur_timelong>timelong){
				long a  = cur_timelong - timelong;
				heartbeart_lilun = (a/(set_heart_time*60000))+1;
			}
		}
		if(heartbeart>heartbeart_lilun){
			heartlv =100;
		}else{
			heartlv = heartbeart * 100 / heartbeart_lilun;
		}
		ParameterMap map = new ParameterMap();
		map.put("datasetId","heartbeat");
		map.put("value",heartlv);
		return map;
	}

	@Async("asyncExecutor")
	@Override
	public void mqAddDevLog(DevLog devLog) {
		mongoEventDao.saveDevLog(devLog);
	}

	@Async("asyncExecutor")
	@Override
	public void mqAddSmokeData(SmokeData smokeData) {
		mongoSmokeDao.saveSmokeData(smokeData);
	}

	@Async("asyncExecutor")
	@Override
	public void mqAddLoginData(LoginData loginData) {
        mongoLoginDao.saveLoginData(loginData);
	}

	@Async("asyncExecutor")
	@Override
	public void mqAddHeartData(HeartData heartData) {
		mongoHeartDao.saveHeartData(heartData);
	}

	@Override
	public ParameterMap isMultiLoginError(String device_id) {
      List<LoginHadleEvent> loginHadleEvents = mongoLoginHandleDao.getAllLoginHandleInfo(device_id);
      long timestamp = 0;
      long value = 0;
      if(loginHadleEvents==null || loginHadleEvents.size()==0){
      	List<LoginData> list = mongoLoginDao.getAllLoginInfo(device_id);
      	if(list.size()>0){
      		if(list.size()>1){
				value = 1;
				timestamp = list.get(list.size()-1).getTimestamp();
			}else{
      			LoginData loginData = list.get(0);
      			long time_login_in = loginData.getTimestamp();
      			DevLog devLog = mongoEventDao.getEarliestEvent(device_id);
      			boolean flag1 = false;
      			if(devLog!=null){
					flag1 =(devLog.getCreateTime()<time_login_in);
				}
				boolean flag2 = false;
      			SmokeData smokeData = mongoSmokeDao.getEarliestSmoke(device_id);
				if(smokeData!=null){
					flag2 =(smokeData.getTimestamp()<time_login_in);
				}
				boolean flag3 = false;
      			HeartData heartData = mongoHeartDao.getEarliestHeartBeat(device_id);
				if(heartData!=null){
					flag3 =(heartData.getTimestamp()<time_login_in);
				}
				boolean flag_totl = flag1 | flag2 | flag3;
				if(flag_totl){
					value = 1;
					timestamp = loginData.getTimestamp();
				}
			}
		}
	  }else{
      	long a = loginHadleEvents.get(loginHadleEvents.size()-1).getTimestamp();
      	List<LoginData> list = mongoLoginDao.getLoginInfoByTime(device_id,a);
		  if(list.size()>0){
			  value = 1;
			  timestamp = list.get(0).getTimestamp();
		  }
	  }

		ParameterMap map = new ParameterMap();
		map.put("datasetId","multlogin");
		map.put("value",value);
		map.put("timestamp",timestamp);
		return map;
	}

	@Async("asyncExecutor")
	@Override
	public void updateDeviceData(Device device) {
		Calendar now = Calendar.getInstance();
		long curtime = now.getTime().getTime();
		now.add(Calendar.DAY_OF_MONTH, -30);
		long histime = now.getTime().getTime()+10000;
		if(histime<device.getCreateTime()){
			histime = device.getCreateTime();
		}
		AepDeviceStatusClient client = AepDeviceStatusClient.newClient()
				.appKey(Const.APPKEY).appSecret(Const.APPSECRET)
				.build();
		JSONObject param = new JSONObject();
		param.put("productId",Const.PRODUCT_ID);
		param.put("deviceId",device.getDeviceId());
		param.put("begin_timestamp",histime);
		param.put("end_timestamp",curtime);
		param.put("page_size",100);
		boolean flag = true;
		String page_timestamp = "";

		do {
			List<HeartData> heartDataList = new ArrayList<>();
			List<SmokeData> smokeDataList = new ArrayList<>();
			List<LoginData> loginDataList = new ArrayList<>();
			try {
				GetDeviceStatusHisInPageRequest request = new GetDeviceStatusHisInPageRequest();
				param.put("page_timestamp",page_timestamp);
				request.setBody(param.toJSONString().getBytes());	//具体格式见前面请求body说明
				GetDeviceStatusHisInPageResponse statusHisInPageResponse = client.getDeviceStatusHisInPage(request);
				String body = new String(statusHisInPageResponse.getBody());
				JSONObject jsonObject = JSON.parseObject(body);
				int code = jsonObject.getIntValue("code");
				page_timestamp = jsonObject.getString("page_timestamp");
				JSONArray array = jsonObject.getJSONArray("deviceStatusList");
				if(code==0){
					if(StringUtils.isEmpty(page_timestamp)){
						flag = false;
					}
					for(int i=0;i<array.size();i++){
						JSONObject obj = array.getJSONObject(i);
						if(obj.containsKey("heartbeat_time")){
							HeartData heartData = JSONObject.parseObject(obj.toJSONString(), HeartData.class);
							heartData.setDeviceId(device.getDeviceId());
							heartDataList.add(heartData);
						}
						else if(obj.containsKey("smoke_state")){
							SmokeData smokeData = JSONObject.parseObject(obj.toJSONString(), SmokeData.class);
							smokeData.setDeviceId(device.getDeviceId());
							smokeDataList.add(smokeData);
						}else if(obj.containsKey("tau_flag")){
							LoginData loginData = JSONObject.parseObject(obj.toJSONString(), LoginData.class);
							loginData.setDeviceId(device.getDeviceId());
							loginDataList.add(loginData);
						}


					}
					try {
						if(heartDataList.size()>0)
							mongoHeartDao.saveHeartDatas(heartDataList);
						if(smokeDataList.size()>0)
							mongoSmokeDao.saveSmokeDatas(smokeDataList);
						if(loginDataList.size()>0)
							mongoLoginDao.saveLoginDatas(loginDataList);
					} catch (Exception e) {
						e.printStackTrace();
						log.error("error:"+e.getMessage(), e);
					}
				}else {
					flag = false;
				}


			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		while (flag);
		client.shutdown();
	}

	@Async("asyncExecutor")
	@Override
	public void updateDeviceEvent(Device device) {
		boolean flag = true;
		String page_timestamp = "";
		int n = 0;
		AepDeviceEventClient client = null;
		do {
			try {
				client = AepDeviceEventClient.newClient()
						.appKey(Const.APPKEY).appSecret(Const.APPSECRET)
						.build();
				Calendar now = Calendar.getInstance();
				now.add(Calendar.DAY_OF_MONTH, -30*n);
				long end_time_long = now.getTime().getTime();
				now.add(Calendar.DAY_OF_MONTH, -30);
				long start_time_long = now.getTime().getTime();
				JSONObject param = new JSONObject();
				param.put("productId",Const.PRODUCT_ID);
				param.put("deviceId",device.getDeviceId());
				param.put("startTime",start_time_long);
				param.put("endTime",end_time_long);
				param.put("pageSize",100);
				param.put("pageTimestamp",page_timestamp);

				QueryDeviceEventListRequest request = new QueryDeviceEventListRequest();
				request.setParamMasterKey(Const.MASTER_APIKEY);
				request.setBody(param.toJSONString().getBytes());	//具体格式见前面请求body说明
				QueryDeviceEventListResponse queryDeviceEventListResponse = client.QueryDeviceEventList(request);
				System.out.println(queryDeviceEventListResponse);
				String body = new String(queryDeviceEventListResponse.getBody());
				JSONObject jsonObject = JSON.parseObject(body);
				int code = jsonObject.getIntValue("code");
				String desc = jsonObject.getString("msg");
				page_timestamp = jsonObject.getString("page_timestamp");

				if(code==0){
					JSONArray array = jsonObject.getJSONObject("result").getJSONArray("list");
					if(StringUtils.isEmpty(page_timestamp)){
						n++;
						page_timestamp = "";
						if(array.size()==0){
							flag = false;
						}
					}
					List<DevLog>  list = JSONObject.parseArray(array.toJSONString(), DevLog.class);
					if(list.size()>0)
						mongoEventDao.saveDevLogs(list);
				}else{
					flag = false;
				}


			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		while (flag);
		client.shutdown();
	}


}
